#include <iostream>
#include <filesystem>
#include <fstream>
#include <memory>
#include <array>
#include <string>
#include <vector>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"


using image_data_t = std::vector<std::pair<std::string, int>>;

struct RawImage {
	int x;
	int y;
	std::shared_ptr<stbi_uc[]> data;
};

struct ObjectProperty {
	//类型
	int type = 0;
	//是否可见
	bool bVisible = true;
	//宽度
	int width = 0;
	//高度
	int height = 0;
	//图片资源
};

int spriteCount = 0;

std::array<ObjectProperty, 100> objectPassArray;	//对象属性数组

std::array<char, 22> var_byte_arr_m = {
	2, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1
};

std::array<char, 13>var_byte_arr_n = {
	2, 3, 3, 3, 6, 3, 3, 6, 3, 3, 3, 3, 3
};

char items[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 4, 2, 3, 3, 3, 3, 3, 3, 2, 3, 2, 2, 2, 3, 2, 3, 3, 3, 2, 3, 5, 3, 3, 3, 3, 3, 3, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, };


std::array<bool, 104> objectPassable = {
	false, true, false, true, true, true, true, false, true, false, false, true, true, true, true, false,
	true, true, true, true, true, true, false, false, true, true, true, true, true, true, false, false, false,
	false, false, false, false, false, false, false, true, true, true, true, false, false, false, false, true, true,
	true, true, false, false, false, false, true, true, true, true, false, false, false, false, true, true, true, true,
	false, false, false, false, true, true, true, true, false, false, false, false, false, false, false, false, false, false,
	false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false
};

enum ActorType {
	ActrorType_None = 0,
	ActorType_GroundItem = 1,			//地面物体 门 隐形路径 隐形墙 门卫 上下楼梯 炼丹炉 云雾
	ActorType_PropertyItem = 2,			//火眼金睛 玄明石 金刚丹
	ActorType_Equip = 4,				//武器
	ActorType_Monster = 8,				//怪物
	ActorType_BusinessMan = 16,			//商人
	ActorType_NPC = 32,					//NPC
};

struct ActorInfo {
	int actorType;
	const char* name;
	int spriteFrameWidth;
	int actorProp1;
	//只有实例化之后才初始化碰撞		69 杨戬 96 32	67 哮天犬 32 32		72 牛魔王 32 45  其它的如果有图则使用帧宽度和帧高度 没有默认32 32
	//int width;				//碰撞宽度
	//int height;				//碰撞高度
};

int var_byte_arr_v[] = { 0, 84, 0, 84, 0, 84, 0, 0, 84, 0, 70, 0, 70, 0, 70, 0, 70, 0, 84, 0, 0, 70, 72, 0, 72, 0, 72, 0, 72, 0, 72, 0, 72, 0, 72, 0, 72, 75, 0, 75, 75, 75, 0, 72, 0, 72, 0, 72, 0, 72, 0, 72, 0, 74, 0, 74, 0, 74, 0, 74, 72, 72, 47, 72, 0, 72, 72, 0, 73, 0, 73, 0, 73, 0, 73, 73, 72, 0, 72, 72, 0, 72, 72, 0, 73, 0, 73, 0, 73, 0, 73, 0, 70, 73, 70, 73, 70, 73, 73, 0, 70, 69, 0, 69, 0, 69, 84, 0, 0, 84, 0, 84, 0, 84, 0, 84, 0, 84, 70, 0, 70, 0, 70, 72, 0, 72, 0, 0, -1, 0, 84, 0, 84, 84, 0, 84, 0, 84, 0, 84, 0, 84, 0, 84, 0, 84, 0, 0, 0, 0, 69, 69, 0, 69, 0, 0, 72, 0, 72, 0, 72, 0, 0, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 0, 87, 87, 87, 87, 87, 87, 0, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 71, 71, 0, 71, 71, 74, 71, 75, 0, 71, 71, 69, 47, 69, 56, 69, 47, 77, 77, 77, 71, 0, 56, 71, 0, 0, 87, 0, 87, 0, 87, 0, 87, 0, 0, 87, 87, 87, 87, 87 };
int var_byte_arr_w[] = { 7, 5, -1, 3, -1, 5, -1, 1, 10, 0, -1, -1, -1, -1, -1, -1, -1, 1, 9, 7, 8, -1, -1, 5, 11, 2, 6, -1, -1, -1, -1, 3, 11, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, -1, 11, -1, 5, 0, 5, 9, 2, 10, 3, -1, -1, 11, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, 10, -1, -1, 9, 0, 1, -1, -1, -1, -1, -1, -1, 3, 11, -1, 0, 3, -1, -1, -1, -1, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, -1, 5, -1, 1, 3, -1, 8, 9, 8, 9, -1, -1, -1, 8, 4, 5, 6, 10, 8, -1, -1, 5, 9, 1, -1, 0, 3, 7, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, -1, -1, 0, -1, -1, -1, -1, -1, -1, 7, -1, 7, -1, 7, 2, 2, -1, 2, -1, -1, -1, 7, -1, -1, -1, -1, -1, -1, -1, -1, 9, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };


std::array< const char*, 88> actorNames = {
	//true,			false,		false,			false,			false,		true,			true,			true,		true,		false, true, false, false}
	"孙悟空",		"黄门",		"红门",			"蓝门",			"封印门",	"门卫",			"隐形路径",		"上楼梯",	"下楼梯",	"炼丹炉",
	//true,			false,		false
	"云雾",			"能挖的墙", "隐形墙",		"火眼金睛",		"生死簿",	"筋斗云",		"芭蕉扇",		"金勺子",	"玄明石",	"千年月桂露",
	"相形变位",		"上行符",	"下行符",		"太公杖",		"捆仙绳",	"幸运币",		"黄钥匙",		"红钥匙",	"蓝钥匙",	"威力丹",
	"金刚丹",		"回春丸",	"长寿丹",		"桃木棒",		"玄铁棒",	"真银棒",		"金箍棒",		"道袍",		"铁甲",		"锁子甲",
	"紫金龙鳞甲",	"天宫小犬", "天宫大犬",		"伴炉童子",		"护庭小神", "守园仙婢",		"护庭校尉",		"巡天卫士", "巡天卫士", "巨力士",
	"执火道人",		"奎木狼",	"执瓶仙侍",		"金刚力士",		"护持迦蓝", "侍案仙女",		"护庭神将",		"赤力韦驮", "护丹老道", "伏魔韦驮",
	"兜率宫星君",	"无量护法", "兜率宫老仙",	"二郎执旗将",	"杀破狼",	"二郎骁骑将",	"尊天韦驮",		"啸天犬",	"太上老君", "杨戬",
	"玉皇大帝",		"玉皇大帝", "牛魔王",		"天蓬元帅",		"巨灵神",	"哪吒",			"路点",			"太白金星", "天宫商人", "乌金棍",
	"银缕锁甲",		"封印门",	"传怪点",		"剧情点",		"嫦娥",		"黄金钥匙",		"日月无极钹",	"菩提老祖"
};

char spriteUnknownProperty[] = {
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
	2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
	0, 3, 3, 3, 4, 2, 3, 3, 3, 3, 
	3, 3, 2, 3, 2, 2, 2, 3, 2, 3, 
	3, 3, 2, 3, 5, 3, 3, 3, 3, 3, 
	3, 0, 0, 0, 2, 2, 0, 0, 0, 0, 
	0, 0, 0, 0, 2, 0, 0, 0, };


/*
* 特殊伤害机制
	this.var_byte_arr_f[74] = 1;    //巨灵神		太公杖
	this.var_byte_arr_f[53] = 1;    //金刚力士
	this.var_byte_arr_f[49] = 1;    //巨力士
	this.var_byte_arr_f[69] = 2;    //杨戬			捆仙绳
*/
ActorInfo actors[] = {
	{ActrorType_None,"孙悟空",32,0},
	//地面物体
	{ActorType_GroundItem,"黄门",32,0},{ActorType_GroundItem,"红门",32,0},{ActorType_GroundItem,"蓝门",32,0},{ActorType_GroundItem,"封印门",45,0},
	{ActorType_GroundItem,"门卫",32,0},{ActorType_GroundItem,"隐形路径",32,0},{ActorType_GroundItem,"上楼梯",32,0},{ActorType_GroundItem,"下楼梯",32,0},{ActorType_GroundItem,"炼丹炉",104,0},
	{ActorType_GroundItem,"云雾",35,2},	{ActorType_GroundItem,"能挖的墙",45,0},	{ActorType_GroundItem,"隐形墙",30,0},	
	//属性物品
	{ActorType_PropertyItem,"火眼金睛",32,0},{ActorType_PropertyItem,"生死簿",32,0},
	{ActorType_PropertyItem,"筋斗云",30,0},{ActorType_PropertyItem,"芭蕉扇",30,0},	{ActorType_PropertyItem,"金勺子",24,0},	{ActorType_GroundItem,"玄明石",25,0},	{ActorType_GroundItem,"千年月桂露",21,0},
	{ActorType_PropertyItem,"相形变位",32,0},{ActorType_PropertyItem,"上行符",25,0},	{ActorType_PropertyItem,"下行符",25,0},{ActorType_PropertyItem,"太公杖",27,0},{ActorType_PropertyItem,"捆仙绳",31,0},
	{ActorType_PropertyItem,"幸运币",27,0},{ActorType_PropertyItem,"黄钥匙",23,0},{ActorType_PropertyItem,"红钥匙",23,0},{ActorType_PropertyItem,"蓝钥匙",23,0},{ActorType_PropertyItem,"威力丹",32,0},
	{ActorType_PropertyItem,"金刚丹",32,0},	{ActorType_PropertyItem,"回春丸",32,0},	{ActorType_PropertyItem,"长寿丹",32,0},	
	//装备
	{ActorType_Equip,"桃木棒",27,0},{ActorType_Equip,"玄铁棒",27,0},{ActorType_Equip,"真银棒",27,0},{ActorType_Equip,"金箍棒",27,0},
	{ActorType_Equip,"道袍",22,0},{ActorType_Equip,"铁甲",22,0},{ActorType_Equip,"锁子甲",16,0},{ActorType_Equip,"紫金龙鳞甲",25,0},
	//怪物
	{ActorType_Monster,"天宫小犬",15,3},{ActorType_Monster,"天宫大犬",20,3},{ActorType_Monster,"伴炉童子",28,3},{ActorType_Monster,"护庭小神",26,4},{ActorType_Monster,"守园仙婢",23,2},
	{ActorType_Monster,"护庭校尉",34,3},{ActorType_Monster,"巡天卫士",35,3},{ActorType_Monster,"巡天卫士",24,3},{ActorType_Monster,"巨力士",33,3},{ActorType_Monster,"执火道人",22,3},
	{ActorType_Monster,"奎木狼",22,3},{ActorType_Monster,"执瓶仙侍",28,2},{ActorType_Monster,"金刚力士",36,3},{ActorType_Monster,"护持迦蓝",38,2},{ActorType_Monster,"侍案仙女",29,2},
	{ActorType_Monster,"护庭神将",34,2},{ActorType_Monster,"赤力韦驮",29,3},{ActorType_Monster,"护丹老道",30,2},{ActorType_Monster,"伏魔韦驮",31,3},{ActorType_Monster,"兜率宫星君",33,3},
	{ActorType_Monster,"无量护法",26,3},{ActorType_Monster,"兜率宫老仙",30,2},{ActorType_Monster,"二郎执旗将",36,3},{ActorType_Monster,"杀破狼",23,5},{ActorType_Monster,"二郎骁骑将",38,3},
	{ActorType_Monster,"尊天韦驮",33,3},{ActorType_Monster,"啸天犬",42,3},{ActorType_Monster,"太上老君",32,3},{ActorType_Monster,"杨戬",78,3},
	{ActorType_Monster,"玉皇大帝",38,3},{ActorType_Monster,"玉皇大帝",36,0},
	//NPC
	{ActorType_NPC,"牛魔王",32,0},
	//怪物
	{ActorType_Monster,"天蓬元帅",39,0},{ActorType_Monster,"巨灵神",59,2},{ActorType_Monster,"哪吒",36,2},		
	//地面物体
	{ActorType_GroundItem,"路点",32,0},	
	//商人
	{ActorType_BusinessMan,"太白金星",29,0},{ActorType_BusinessMan,"天宫商人",37,0},
	//装备
	{ActorType_Equip,"乌金棍",27,0},{ActorType_Equip,"银缕锁甲",17,0},
	//零散的地面物品
	{ActorType_GroundItem,"封印门",32,0},{ActorType_GroundItem,"传怪点",32,0},	{ActorType_GroundItem,"剧情点",32,0},
	//NPC
	{ActorType_NPC,"嫦娥",29,2},
	//属性物品
	{ActorType_PropertyItem,"黄金钥匙",27,0},{ActorType_PropertyItem,"日月无极钹",32,0},
	//NPC
	{ActorType_NPC,"菩提老祖",36,0}
};

const char* equipItemDescribs[] = {
	"", 
	"\\cdddddd一根相当长的木制长棍,新手必备.有了它杀人越货不慌不愁.\n\\c00ff00装备: 攻击+10.\n\\cFFCC00\"看上去似乎会断掉。\".", 
	"\\cdddddd乌黑油亮，显然经历过多人之手。\n\\c00ff00装备: 攻击+30.\n\\cFFCC00\"很粗很结实！\".", 
	"\\cdddddd银棍，恩，有这个名字就足够了。\n\\c00ff00装备: 攻击+70.\n\\cFFCC00\"只是根银棍\".", 
	"\\cdddddd因乘天地之灵气，集日月之精华乃“万木之灵，灵木之尊”。\n\\c00ff00装备: 攻击+120.\n\\cFFCC00\"木之精华，削铁断金\".", 
	"\\cdddddd您的需要，它知道；您的需求，它满足。它好，你也好，龙王后宫，镇宫之宝！\n\\c00ff00装备: 攻击+220.\n\\cFFCC00\"不要迷恋它，它只是一根传说。\".", 
	"", 
	"\\cdddddd没有太多的装饰，一件非常朴素、轻便的布衣.\n\\c00ff00装备: 防御+10.\n\\cFFCC00\"看上去有不少人用过了。\".", 
	"\\cdddddd保暖御寒，腰不酸，腿不疼，走路也有劲了。\n\\c00ff00装备: 防御+30.\n\\cFFCC00\"豹纹，性感又野性，今年天宫最流行的皮草款式\".", 
	"\\cdddddd如果没有上面的那行字，它也算是个杰作。\n\\c00ff00装备: 防御+70.\n\\cFFCC00\"上面写着'办四级神仙证书，回收二手莲花宝座'\".", 
	"\\cdddddd华丽的装饰，就是有点旧。\n\\c00ff00装备: 防御+120.\n\\cFFCC00\"别人穿过的极品。\".", 
	"\\cdddddd东海龙鳞编织而成，限量版，天上天下，只此一款。\n\\c00ff00装备: 防御+220.\n\\cFFCC00\"更轻薄，更透气，更多防护，更多安心\"." };


enum class ItemType {
	Weapon,			//武器
	Cloth,			//衣服
	Attribue,		//属性物品
	Health,			//生命值物品
};

struct Item {
	ItemType itemType;
	int itemID;
	std::string name;		//名字
	int priority;			//优先级，同类型的高优先级物品无法被低优先级物品替代
	int value;				//属性值
	std::string describ;	//物品描述
};

Item equipItems[] = {
	{ItemType::Weapon,	33, "桃木棒",		1,	10,		"\\cdddddd一根相当长的木制长棍,新手必备.有了它杀人越货不慌不愁.\n\\c00ff00装备: 攻击+10.\n\\cFFCC00\"看上去似乎会断掉。\"."},
	{ItemType::Weapon,	34,	"玄铁棒",		2,	30,		"\\cdddddd乌黑油亮，显然经历过多人之手。\n\\c00ff00装备: 攻击+30.\n\\cFFCC00\"很粗很结实！\"."},
	{ItemType::Weapon,	35, "真银棒",		3,	70,		"\\cdddddd银棍，恩，有这个名字就足够了。\n\\c00ff00装备: 攻击+70.\n\\cFFCC00\"只是根银棍\"."},
	{ItemType::Weapon,	36, "金箍棒",		4,	120,	"\\cdddddd您的需要，它知道；您的需求，它满足。它好，你也好，龙王后宫，镇宫之宝！\n\\c00ff00装备: 攻击+220.\n\\cFFCC00\"不要迷恋它，它只是一根传说。\"."},
	{ItemType::Weapon,	79, "乌金棍",		5,	220,	"\\cdddddd您的需要，它知道；您的需求，它满足。它好，你也好，龙王后宫，镇宫之宝！\n\\c00ff00装备: 攻击+220.\n\\cFFCC00\"不要迷恋它，它只是一根传说。\"."},

	{ItemType::Weapon,	37, "道袍",			1,	10,		"\\cdddddd没有太多的装饰，一件非常朴素、轻便的布衣.\n\\c00ff00装备: 防御+10.\n\\cFFCC00\"看上去有不少人用过了。\".",},
	{ItemType::Weapon,	38, "铁甲",			2,	30,		"\\cdddddd保暖御寒，腰不酸，腿不疼，走路也有劲了。\n\\c00ff00装备: 防御+30.\n\\cFFCC00\"豹纹，性感又野性，今年天宫最流行的皮草款式\".",},
	{ItemType::Weapon,	39, "锁子甲",		3,	70,		"\\cdddddd如果没有上面的那行字，它也算是个杰作。\n\\c00ff00装备: 防御+70.\n\\cFFCC00\"上面写着'办四级神仙证书，回收二手莲花宝座'\".",},
	{ItemType::Weapon,	40, "紫金龙鳞甲",	4,	120,	"\\cdddddd华丽的装饰，就是有点旧。\n\\c00ff00装备: 防御+120.\n\\cFFCC00\"别人穿过的极品。\".",},
	{ItemType::Weapon,	80, "银缕锁甲",		5,	220,	"\\cdddddd东海龙鳞编织而成，限量版，天上天下，只此一款。\n\\c00ff00装备: 防御+220.\n\\cFFCC00\"更轻薄，更透气，更多防护，更多安心\"."},
};


//交互对象图像数组
std::array<unsigned char*, 88> actorSpriteImages;

template<typename Stream>
short readBinaryShort(Stream& fs)
{
	short size = fs.get() & 0xFF | fs.get() << 8 & 0xFF00;
	return size;
}

void initPassthrough(int width, int height, const std::shared_ptr<char[]>& passableArray, std::vector<std::vector<bool>>& result) {
	int n = 0;
	char objectPassIndex = 0;
	int line = 0;
	while (line < height) {
		int col = 0;
		while (col < width) {
			objectPassIndex = passableArray[n];
			result[line][col] = objectPassIndex < objectPassable.size() ? objectPassable[objectPassIndex] : false;
			++col;
			n += 2;
		}
		++line;
		n += width << 1;
	}
}


bool saveImages(const std::filesystem::path& basePath, const std::filesystem::path& savePath, const std::string& filename, int count)
{
	try {
		std::filesystem::path path = basePath / filename;

		if (!std::filesystem::exists(savePath)) {
			if (!std::filesystem::create_directories(savePath)) {
				return false;
			}
		}

		std::ifstream fs;
		fs.open(path, std::ios::binary);
		if (fs.fail()) {
			return false;
		}
		//循环转存
		for (int i = 0; i < count; i++) {
			int size = readBinaryShort(fs);
			if (!size) {
				std::cout << "get size failed !" << std::endl;
				return false;
			}
			auto data = std::shared_ptr<char[]>(new char[size]());
			fs.read(data.get(), size);
			std::ofstream ofs;
			ofs.open(savePath / (filename + "_" + std::to_string(i) + ".png"), std::ios::binary);
			ofs.write(data.get(), size);
			ofs.close();
		}

	} catch (const std::exception& e) {
		std::cout << "error: " << e.what() << std::endl;
	}
	return true;
}

bool loadResourceImages(const std::filesystem::path& basePath, const std::string& filename, int count, std::vector<RawImage>& imageDatas)
{
	try {
		std::filesystem::path path = basePath / filename;
		std::ifstream fs;
		fs.open(path, std::ios::binary);
		if (fs.fail()) {
			return false;
		}
		//循环转存
		for (int i = 0; i < count; i++) {
			int size = readBinaryShort(fs);
			if (!size) {
				std::cout << "get size failed !" << std::endl;
				return false;
			}
			auto data = std::shared_ptr<char[]>(new char[size]());
			fs.read(data.get(), size);
			int x = 0, y = 0;
			int n = 4;
			auto imageData = stbi_load_from_memory((const stbi_uc*)data.get(), size, &x, &y, &n, 0);
			imageDatas.push_back({ x,y, std::shared_ptr<stbi_uc[]>(imageData,free) });
		}

	} catch (const std::exception& e) {
		std::cout << "error: " << e.what() << std::endl;
	}
	return true;
}

void loadSprite(int spriteType, int spriteIndex)
{
	auto data = actorSpriteImages[spriteType];

}

//加载对象属性
int loadSpritePropertyInternal(int spriteType, int n3, int s, int n4)
{
	loadSprite(spriteType, spriteCount);
	return 0;
}

bool loadLevelSprites(const std::filesystem::path& basePath, int nLevel)
{
	try {
		auto levelFile = basePath / ("sprite" + std::to_string(nLevel));
		if (!std::filesystem::exists(levelFile)) {
			return false;
		}
		std::ifstream ifs;
		ifs.open(levelFile, std::ios::binary);
		if (ifs.fail()) {
			return false;
		}

		int n5 = 0;

		int nCount = readBinaryShort(ifs) & 0xFFFF | readBinaryShort(ifs) << 16;
		std::cout << "nCount: " << nCount << std::endl;
		for (int i = 0; i < nCount; i++) {
			int spriteType = ifs.get();
			int savedX = readBinaryShort(ifs);
			int savedY = readBinaryShort(ifs);

			savedX = (savedX + 16 >> 5) << 5;
			savedY = (savedY + 16 >> 5) << 5;

			std::cout << "idx:" << i << ", spriteType: " << spriteType << ", name: " << actorNames[spriteType] << ", x: " << savedX << ", y: " << savedY << std::endl;

			switch (spriteType) {
			case 6:		//隐形路径
			case 12: {	//隐形墙
				loadSpritePropertyInternal(spriteType, savedX, savedY, 0);
				objectPassArray[spriteType].bVisible = false;
			}break;
			case 9: {	//炼丹炉
				n5 = ifs.get();
				loadSpritePropertyInternal(spriteType, savedX, savedY, n5);
			}break;
			case 5:		//门卫
			case 81: {	//封印门
				n5 = ifs.get() + 1;
				spriteType = loadSpritePropertyInternal(spriteType, savedX, savedY, n5);
				objectPassArray[spriteType].bVisible = false;
			}break;
			case 83: {	//剧情点
				n5 = ifs.get();
				spriteType = loadSpritePropertyInternal(spriteType, savedX, savedY, n5);
				objectPassArray[spriteType].bVisible = false;
			}break;
			case 7:		//上楼梯
			case 8: {	//下楼梯
				n5 = ifs.get() | ifs.get() << 8;
				loadSpritePropertyInternal(spriteType, savedX, savedY, n5);
			}break;
			case 4:		//封印门
			case 57:	//赤力韦驮
			case 59:	//伏魔韦驮
			case 70:	//玉皇大帝
			case 71:	//玉皇大帝
			case 72:	//牛魔王
			case 73: {	//天蓬元帅
				n5 = ifs.get() + 1;
				loadSpritePropertyInternal(spriteType, savedX, savedY, n5);
			}break;
			case 77: {	//太白金星
				n5 = ifs.get();
				n5 = n5 & 0xFF | var_byte_arr_m[n5 - 1] << 8;
				loadSpritePropertyInternal(spriteType, savedX, savedY, n5);
			}break;
			case 78: {	//天宫商人
				n5 = ifs.get();
				n5 = n5 & 0xFF | var_byte_arr_n[n5 - 1] << 8;
				loadSpritePropertyInternal(spriteType, savedX, savedY, n5);
			}break;
			case 76:	//路点
			case 82: {	//传怪点
				n5 = ifs.get() | (ifs.get() + (1 << 8));
				spriteType = loadSpritePropertyInternal(spriteType, savedX, savedY, n5);
				objectPassArray[spriteType].bVisible = false;
			}break;
			default: {
				loadSpritePropertyInternal(spriteType, savedX, savedY, 0);
			}
			}
		}
		ifs.close();
	} catch (const std::exception& e) {
		std::cout << "error: " << e.what() << std::endl;
		return false;
	}
	return true;
}

bool loadLevel(const std::filesystem::path& basePath, int nLevel)
{
	try {
		auto levelFile = basePath / ("maplv" + std::to_string(nLevel));
		if (!std::filesystem::exists(levelFile)) {
			return false;
		}
		//打开文件并读取size
		std::ifstream ifs;
		ifs.open(levelFile, std::ios::binary);
		if (ifs.fail()) {
			return false;
		}
		int nLogicWidth = readBinaryShort(ifs) / 2;
		int nLogicHeight = readBinaryShort(ifs) / 2;
		std::cout << "nWidth: " << nLogicWidth << ", nHeight: " << nLogicHeight << std::endl;
		int nSize = nLogicWidth * nLogicHeight * 4;

		int pixelWidth = nLogicWidth * 32;
		int pixelHeight = nLogicHeight * 32;
		std::cout << "pixelWidth: " << pixelWidth << ", pixelHeight: " << pixelHeight << std::endl;
		//猜测是通行路径
		auto mapPassBitmap = std::vector<std::vector<bool>>();
		mapPassBitmap.resize(nLogicHeight);
		for (auto& line : mapPassBitmap) {
			line.resize(nLogicWidth);
		}

		auto passableArray = std::shared_ptr<char[]>(new char[nSize]);
		auto buffer_2 = std::shared_ptr<char[]>(new char[nSize]);
		ifs.read(passableArray.get(), nSize);
		ifs.read(buffer_2.get(), nSize);
		//初始化地图通行信息
		initPassthrough(nLogicWidth, nLogicHeight, passableArray, mapPassBitmap);
		//加载sprite
		loadLevelSprites(basePath, nLevel);


#if 1
		for (int y = 0; y < nLogicHeight; y++) {
			for (int x = 0; x < nLogicWidth; x++) {
				std::cout << (mapPassBitmap[y][x] ? " " : "+");
			}
			std::cout << std::endl;
		}
#else
		for (int y = 0; y < nLogicHeight * 2; y++) {
			for (int x = 0; x < nLogicWidth * 2; x++) {
				std::cout << std::to_string(passableArray[y * nLogicWidth * 2 + x]);
			}
			std::cout << std::endl;
		}
#endif

	} catch (const std::exception& e) {
		std::cout << "error: " << e.what() << std::endl;
	}
	return true;
}

int main(int argc, char** argv)
{
	std::cout << "str len is: " << strlen("\\cdddddd一根相当长的木制长棍,新手必备.有了它杀人越货不慌不愁.\n\\c00ff00装备: 攻击+10.\n\\cFFCC00\"看上去似乎会断掉。\".") << std::endl;
	image_data_t images = {
		{"sflogo",8}, {"mapbg",1}, {"map",12}, {"actor",4}, {"sptmap",13}, {"sptprop", 23},
		{"sptarm",10}, {"sptenemy1",20}, {"ui",25}, {"xtq",6}, {"menu",2}, {"intro",2},
		{"face",12},{ "sptenemy2",20},{ "end",1}, {"load",2}
	};

	std::filesystem::path path = std::filesystem::path(argv[0]).parent_path() / "resources";
#if 1
	if (!std::filesystem::exists("D:\\test")) {
		std::error_code ec;
		std::filesystem::create_directories("D:\\test", ec);
	}
	for (const auto& pair : images) {
		saveImages(path, "D:\\test", pair.first, pair.second);
		//std::vector<RawImage> images;
		//loadResourceImages(path, pair.first, pair.second, images);
	}
#else
	for (int i = 0; i < 55; i++) {
		std::cout << "load level: " << i << std::endl;
		loadLevel(path, i);
	}
#endif
	system("pause");
	return 0;
}